package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.system.domain.SysAlert;
import com.ruoyi.system.domain.SysAlertConfig;
import com.ruoyi.system.domain.SysDeviceLocation;
import com.ruoyi.system.domain.SysHealthData;
import com.ruoyi.system.domain.qo.AlertListQo;
import com.ruoyi.system.domain.vo.AlertLevelNameCount;
import com.ruoyi.system.domain.vo.AlertListVo;
import com.ruoyi.system.domain.vo.SysAlertDetailVo;
import com.ruoyi.system.mapper.SysHealthDataMapper;
import com.ruoyi.system.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysAlertMapper;
import com.ruoyi.system.mapper.SysAlertConfigMapper;
import com.ruoyi.system.domain.vo.IndexVo;
import org.springframework.transaction.annotation.Transactional;

/**
 * 预警列表 服务层实现
 *
 * @author ruoyi
 */
@Service
public class SysAlertServiceImpl implements ISysAlertService {
    private final SysAlertMapper sysAlertMapper;
    private final SysAlertConfigMapper sysAlertConfigMapper;
    private final IAppUserService appUserService;
    private final ISysDeviceLocationService sysDeviceLocationService;
    private final ISysDictDataService sysDictDataService;
    private final SysHealthDataMapper sysHealthDataMapper;

    public SysAlertServiceImpl(SysAlertMapper sysAlertMapper, SysAlertConfigMapper sysAlertConfigMapper,
                               IAppUserService appUserService, ISysDeviceLocationService sysDeviceLocationService,
                               ISysDictDataService sysDictDataService, SysHealthDataMapper sysHealthDataMapper) {
        this.sysAlertMapper = sysAlertMapper;
        this.sysAlertConfigMapper = sysAlertConfigMapper;
        this.appUserService = appUserService;
        this.sysDeviceLocationService = sysDeviceLocationService;
        this.sysDictDataService = sysDictDataService;
        this.sysHealthDataMapper = sysHealthDataMapper;
    }

    /**
     * 查询预警信息
     *
     * @param id 预警ID
     * @return 预警信息
     */
    @Override
    public SysAlert selectSysAlertById(Long id) {
        return sysAlertMapper.selectSysAlertById(id);
    }

    @Override
    public SysAlertDetailVo getAlertDetailById(Long id) {

        SysAlert sysAlert = sysAlertMapper.selectSysAlertById(id);

        SysAlertDetailVo sysAlertDetailVo = new SysAlertDetailVo();
        BeanUtils.copyProperties(sysAlert, sysAlertDetailVo);

        AppUser user = appUserService.selectAppUserById(sysAlert.getUserId());
        if (user != null) {
            sysAlertDetailVo.setUserName(user.getLoginName());
            sysAlertDetailVo.setMobile(user.getUserMobile());
        }
        return sysAlertDetailVo;
    }

    /**
     * 查询预警列表
     *
     * @param sysAlert 预警信息
     * @return 预警集合
     */
    @Override
    public List<SysAlert> selectSysAlertList(SysAlert sysAlert) {
        return sysAlertMapper.selectSysAlertList(sysAlert);
    }

    @Override
    public List<AlertListVo> selectAlertList(AlertListQo alertListQo) {
        return sysAlertMapper.selectAlertList(alertListQo);
    }

    @Override
    public List<AlertListVo> selectAggregateList(AlertListQo alertListQo) {
        return sysAlertMapper.selectAggregateList(alertListQo);
    }

    /**
     * 新增预警
     *
     * @param sysAlert 预警信息
     * @return 结果
     */
    @Override
    public int insertSysAlert(SysAlert sysAlert) {
        return sysAlertMapper.insertSysAlert(sysAlert);
    }

    /**
     * 修改预警
     *
     * @param sysAlert 预警信息
     * @return 结果
     */
    @Override
    public int updateSysAlert(SysAlert sysAlert) {
        return sysAlertMapper.updateSysAlert(sysAlert);
    }

    /**
     * 删除预警信息
     *
     * @param id 预警ID
     * @return 结果
     */
    @Override
    public int deleteSysAlertById(Long id) {
        return sysAlertMapper.deleteSysAlertById(id);
    }

    /**
     * 批量删除预警信息
     *
     * @param ids 需要删除的预警ID
     * @return 结果
     */
    @Override
    public int deleteSysAlertByIds(Long[] ids) {
        return sysAlertMapper.deleteSysAlertByIds(ids);
    }

    /**
     * 定时任务：根据预警配置和健康数据生成预警
     * 以设备为维度，遍历所有设备的最新健康数据，结合预警配置生成预警
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateAlertsFromHealthData(SysHealthData healthData) {

        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType("warning_threshold");
        List<SysDictData> sysDictDataList = sysDictDataService.selectDictDataList(sysDictData);

        // 1. 获取所有预警配置
        List<SysAlertConfig> alertConfigs = sysAlertConfigMapper.selectSysAlertConfigList(new SysAlertConfig());
        if (alertConfigs.isEmpty()) {
            return;
        }
        Map<String, String> healthDataMap = JSONObject.parseObject(
                JSONObject.toJSONString(healthData),
                new TypeReference<Map<String, String>>() {
                }
        );

        // 根据 projectCate 分组，并按 alertLevel 排序
        Map<String, List<SysAlertConfig>> groupedByProjectCate = alertConfigs.stream()
                .sorted(Comparator.comparing(SysAlertConfig::getAlertLevel))
                .collect(Collectors.groupingBy(o -> o.getProjectCate().toLowerCase().replace("_", "")));

        List<Map<String, String>> healthDataMapList = new ArrayList<>();
        for (SysDictData data : sysDictDataList) {
            List<SysHealthData> list = sysHealthDataMapper.selectSysHealthDataByType(data.getDictLabel(), Long.parseLong(data.getDictValue()));
            list.forEach(item -> healthDataMapList.add(JSONObject.parseObject(JSONObject.toJSONString(item), new TypeReference<Map<String, String>>() {
            })));

            if (list.size() != Long.parseLong(data.getDictValue())) {
                continue;
            }

            List<SysAlertConfig> itemAlertConfigs = groupedByProjectCate.get(data.getDictLabel().toLowerCase().replace("_", ""));
            if (Objects.isNull(itemAlertConfigs) || itemAlertConfigs.isEmpty()) {
                continue;
            }

            // 结合预警配置生成预警
            for (SysAlertConfig config : itemAlertConfigs) {
                // 判断数据是否有效， 判断当前数据，避免出现手动测量时数据为0 的情况
                if (!validateHealthData(healthDataMap, config)) {
                    continue;
                }

                // 根据比较规则判断是否生成预警
                int alertCount = 0;
                for (Map<String, String> dataMap : healthDataMapList) {

                    String featureValue = dataMap.get(config.getProjectCate());
                    Integer healthValue = parseHealthValue(featureValue, config);
                    /*如果当天数据该指标值为空，意味着本条数据是用来测量其他*/
                    if (Objects.isNull(healthValue)) {
                        continue;
                    }

                    // 根据比较规则判断是否生成预警
                    if ("gt".equals(config.getCompareRule()) && healthValue > config.getThreshold()) {
                        alertCount += 1;
                    } else if ("lt".equals(config.getCompareRule()) && healthValue < config.getThreshold()) {
                        alertCount += 1;
                    }
                }

                if (alertCount == 0) {
                    /*如果所有数据都为正常数据，将此前该类型报警置为正常状态*/
                    SysAlert sysAlert = new SysAlert();
                    sysAlert.setUserId(healthData.getUserId());
                    sysAlert.setAlertConfigId(config.getId());
                    sysAlert.setDeviceId(healthData.getDeviceId());
                    sysAlertMapper.recoveryAlert(sysAlert);
                } else if (alertCount == healthDataMapList.size()) {
                    /*如果所有数据都为异常数据， 产生报警记录*/
                    // 生成预警数据
                    SysAlert alert = getAlert(healthData, config);
                    alert.setDataId(list.stream().map(SysHealthData::getId).collect(Collectors.toList()).toString());
                    /*获取gps数据*/
                    SysDeviceLocation gpsData = sysDeviceLocationService.selectLatestLocationByUserIdAndDeviceId(healthData.getUserId(), healthData.getDeviceId());
                    if (gpsData != null) {
                        alert.setLocation(gpsData.getLongitude() + "," + gpsData.getLatitude());
                    }

                    /*同一个大类型的预警只保留一条， 所以需要把之前相关类型的预警恢复*/
                    SysAlert sysAlert = new SysAlert();
                    sysAlert.setUserId(healthData.getUserId());
                    sysAlert.setAlertConfigId(config.getId());
                    sysAlert.setDeviceId(healthData.getDeviceId());
                    sysAlertMapper.recoveryRelatedAlert(sysAlert);

                    // 保存预警数据
                    sysAlertMapper.insertSysAlert(alert);
                    break;
                }
            }
        }
    }

    private boolean validateHealthData(Map<String, String> healthDataMap, SysAlertConfig config) {

        // 解析健康数据的特征值
        String featureValue = healthDataMap.get(config.getProjectCate());
        Integer healthValue = parseHealthValue(featureValue, config);
        /*如果有数据为空，跳过本条验证*/
        return Objects.nonNull(healthValue);
    }

    private static SysAlert getAlert(SysHealthData healthData, SysAlertConfig config) {
        SysAlert alert = new SysAlert();
        alert.setUserId(healthData.getUserId());
        alert.setDeviceId(healthData.getDeviceId());
        alert.setAlertLevel(config.getAlertLevel());
        alert.setAlertStatus("0");
        alert.setAlertContent(config.getProjectName() + " " + config.getItemName() + " 超出阈值");
        alert.setAlertConfigId(config.getId());
        alert.setAlertTime(new Date());
        alert.setCreateTime(new Date());
        alert.setUpdateTime(new Date());
        // 根据项目类别设置相应的健康数据字段
        alert.setHeartRate(healthData.getHeartRate());
        alert.setBloodPressure(healthData.getBloodPressure());
        alert.setBloodOxygen(healthData.getBloodOxygen());
        return alert;
    }

    /**
     * 解析健康数据的特征值
     */
    private Integer parseHealthValue(String featureValue, SysAlertConfig config) {

        if (StringUtils.isEmpty(featureValue)) {
            return null;
        }

        String projectCate = config.getProjectCate();
        String itemCate = config.getItemCate();
        try {
            if ("blood_pressure".equals(projectCate)) {
                // 血压数据格式为"收缩压,舒张压"
                String[] parts = featureValue.split(",");
                if ("diastolic".equals(itemCate)) {
                    return Integer.parseInt(parts[0]);
                } else if ("systolic".equals(itemCate)) {
                    return Integer.parseInt(parts[1]);
                } else {
                    return null;
                }
            } else {
                /*如果是0，认定为异常数据*/
                if (StringUtils.equals("0", featureValue)) {
                    return null;
                }
                return Integer.parseInt(featureValue);
            }
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Map<String, Object>> countAlertByLevelAndName() {

        List<AlertLevelNameCount> list = sysAlertMapper.countAlertByLevelAndName();

        Map<String, List<AlertLevelNameCount>> map = list.stream()
                .collect(Collectors.groupingBy(AlertLevelNameCount::getAlertLevel));

        List<Map<String, Object>> result = new ArrayList<>();
        map.forEach((level, levelList) -> {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("alert_level", level);
            resultMap.put("data", levelList);
            result.add(resultMap);
        });
        return result;
    }

    @Override
    public Map<String, Long> getTodayAlertCount() {
        Map<String, Long> todayAlertCount = new HashMap<>();
        Long todayAlert = sysAlertMapper.getTodayAlertCount(null);
        Long currentAlert = sysAlertMapper.getTodayAlertCount("1");
        todayAlertCount.put("todayAlert", todayAlert);
        todayAlertCount.put("currentAlert", currentAlert);
        return todayAlertCount;
    }

    @Override
    public Map<String, List<IndexVo>> countAlertByMinutes(Long minutes) {
        Map<String, List<IndexVo>> result = new HashMap<>();
        List<IndexVo> firstStats = sysAlertMapper.countAlertByMinutes(minutes, "1");
        result.put("一级预警", firstStats);
        List<IndexVo> secondStats = sysAlertMapper.countAlertByMinutes(minutes, "2");
        result.put("二级预警", secondStats);
        List<IndexVo> thirdStats = sysAlertMapper.countAlertByMinutes(minutes, "3");
        result.put("三级预警", thirdStats);
        return result;
    }

    @Override
    public Map<String, List<IndexVo>> countAlertByHour() {
        Map<String, List<IndexVo>> result = new HashMap<>();
        List<IndexVo> firstStats = sysAlertMapper.countAlertByHour("1");
        result.put("一级预警", firstStats);
        List<IndexVo> secondStats = sysAlertMapper.countAlertByHour("2");
        result.put("二级预警", secondStats);
        List<IndexVo> thirdStats = sysAlertMapper.countAlertByHour("3");
        result.put("三级预警", thirdStats);
        return result;
    }

    @Override
    public Map<String, List<IndexVo>> countAlertByDay() {
        Map<String, List<IndexVo>> result = new HashMap<>();
        List<IndexVo> firstStats = sysAlertMapper.countAlertByDay("1");
        result.put("一级预警", firstStats);
        List<IndexVo> secondStats = sysAlertMapper.countAlertByDay("2");
        result.put("二级预警", secondStats);
        List<IndexVo> thirdStats = sysAlertMapper.countAlertByDay("3");
        result.put("三级预警", thirdStats);
        return result;
    }

    @Override
    public SysAlert selectLatestAlertByUserId(Long userId) {
        return sysAlertMapper.selectLatestAlertByUserId(userId);
    }
}